package com.hexb.core.config

import org.apache.shiro.cache.ehcache.EhCacheManager
import org.apache.shiro.mgt.SecurityManager
import org.apache.shiro.realm.Realm
import org.apache.shiro.realm.text.IniRealm
import org.apache.shiro.spring.LifecycleBeanPostProcessor
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor
import org.apache.shiro.spring.web.ShiroFilterFactoryBean
import org.apache.shiro.web.mgt.DefaultWebSecurityManager
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
import org.springframework.boot.web.servlet.FilterRegistrationBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.DependsOn
import org.springframework.web.filter.DelegatingFilterProxy

import javax.annotation.Resource

/**
 * @Package : com.hexb.core.config
 * @Author : hexb 
 * @Date : 2018-08-23 14:06
 */
@Configuration
@ConditionalOnProperty(value = 'project.shiro', havingValue = 'true')
class ShiroConfig {

    /**
     * LifecycleBeanPostProcessor，这是个DestructionAwareBeanPostProcessor的子类，
     * 负责org.apache.shiro.util.Initializable类型bean的生命周期的，初始化和销毁。
     * 主要是AuthorizingRealm类的子类，以及EhCacheManager类。
     */
    @Bean(name = 'lifecycleBeanPostProcessor')
    LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        new LifecycleBeanPostProcessor()
    }


    @Bean
    @ConditionalOnMissingBean
    EhCacheManager ehCacheManager() {
        new EhCacheManager()
    }

    @Bean
    @ConditionalOnMissingBean
    Realm userRealm() {
        new IniRealm('classpath:user.ini')
    }

    /**
     * 配置securityManager
     */
    @Bean
    @Resource
    @ConditionalOnMissingBean
    SecurityManager createSecurityManager(Realm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager()
        securityManager.setRealm(userRealm)
        securityManager.setCacheManager(ehCacheManager())
        securityManager
    }

    /**
     * 配置shiroFilter
     */
    @Bean(name = 'shiroFilter')
    @Resource
    @ConditionalOnMissingBean
    ShiroFilterFactoryBean shiroFilterBean(Realm userRealm) {
        ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean()
        bean.setSecurityManager(createSecurityManager(userRealm))
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>()
        bean.setFilterChainDefinitionMap(filterChainDefinitionMap)
        bean
    }

    /**
     * spring-boot方式配置filter
     */
    @Bean
    @ConditionalOnMissingBean
    FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean registration = new FilterRegistrationBean()
        registration.setFilter(new DelegatingFilterProxy('shiroFilter'))
        registration.setEnabled(true);
        registration.addUrlPatterns('/*')
        registration.setOrder(1)
        registration
    }

    /**
     * 开启shiro注解
     */
    @Bean
    @DependsOn('lifecycleBeanPostProcessor')
    @ConditionalOnMissingBean
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator()
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true)
        defaultAdvisorAutoProxyCreator
    }

    @Bean
    @Resource
    @ConditionalOnMissingBean
    AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(Realm userRealm) {
        AuthorizationAttributeSourceAdvisor aASA = new AuthorizationAttributeSourceAdvisor()
        aASA.setSecurityManager(createSecurityManager(userRealm))
        aASA
    }

}
